home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 21 / Cream of the Crop 21 (Terry Blount) (October 1996).iso / os2 / fst03f.zip / fst.c < prev    next >
C/C++ Source or Header  |  1996-08-12  |  41KB  |  1,560 lines

  1. /* fst.c -- Main module of fst
  2.    Copyright (c) 1995-1996 by Eberhard Mattes
  3.  
  4. This file is part of fst.
  5.  
  6. fst is free software; you can redistribute it and/or modify it
  7. under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. fst is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with fst; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 59 Temple Place - Suite 330,
  19. Boston, MA 02111-1307, USA.  */
  20.  
  21.  
  22. #define INCL_DOSDEVIOCTL
  23. #define INCL_DOSNLS
  24. #include <os2.h>
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <stdarg.h>
  28. #include <string.h>
  29. #include <ctype.h>
  30. #include <errno.h>
  31. #include "fst.h"
  32. #include "crc.h"
  33. #include "diskio.h"
  34. #include "fat.h"
  35. #include "do_hpfs.h"
  36. #include "do_fat.h"
  37.  
  38. static char banner[] =
  39. "fst 0.3f -- Copyright (c) 1995-1996 by Eberhard Mattes\n";
  40.  
  41. /* Increase the heap for -Zsys to 64MB. */
  42. unsigned _sys_heap_size = 0x4000000;
  43.  
  44. char verbose;                   /* Non-zero for `check -v' and `save -v' */
  45. char sector_number_format;      /* 'x' for `-x', 0 otherwise */
  46. char a_info;                    /* Non-zero for `info' action */
  47. char a_save;                    /* Non-zero for `save' action */
  48. char a_check;                   /* Non-zero for `check' action */
  49. char a_what;                    /* Non-zero for `info <number>' action */
  50. char a_where;                   /* Non-zero for `info <path>' action */
  51. char a_copy;                    /* Non-zero for `copy' action */
  52. char a_dir;                     /* Non-zero for `dir' action */
  53. char a_find;                    /* Non-zero for finding a file */
  54. char plenty_memory;             /* Non-zero for `check -m' */
  55. char check_unused;              /* Non-zero for `check -u' */
  56. char check_pedantic;            /* Non-zero for `check -p' */
  57. char show_unused;               /* Non-zero for `info -u' */
  58. char show_free_frag;            /* Non-zero for `info -f' */
  59. char show_frag;                 /* Non-zero for `check -f' */
  60. char show_eas;                  /* Non-zero for `info -e <path>' */
  61. char show_summary;              /* Non-zero for `check -s' */
  62. char force_fs;                  /* Non-zero to force to a specific fs */
  63. ULONG what_sector;              /* Sector number for `info <number>' action */
  64. char what_cluster_flag;         /* `what_sector' is a cluster number */
  65. const char *find_path;          /* (Remainder of) pathname for a_find */
  66.  
  67. /* This table maps lower-case letters to upper case, using the current
  68.    code page. */
  69. BYTE cur_case_map[256];
  70.  
  71. FILE *diag_file;                /* Stream for diagnostics */
  72. FILE *prog_file;                /* Stream for progress report */
  73. static FILE *info_file;         /* Stream for information */
  74.  
  75. static int warning_count[2];    /* Index 0: warnings, index 1: errors */
  76.  
  77. static char list_going;         /* Non-zero if list started */
  78. static int list_x;              /* Column */
  79. static char list_msg[80];       /* Message */
  80.  
  81. /* path_chain_new() tries to avoid malloc()'s memory overhead by
  82.    allocating reasonably big buffers out of which the strings and
  83.    path_chains will be allotted.  Fortunately, we never free those
  84.    structures. */
  85.  
  86. struct str_buf
  87. {
  88.   char *buf;
  89.   size_t size;
  90.   size_t used;
  91.   struct str_buf *next;
  92. };
  93.  
  94. struct str_buf *str_buf_head;
  95.  
  96. static path_chain *pc_buf;
  97. static size_t pc_count;
  98. static size_t pc_used;
  99.  
  100. /* Clean up and terminate the process.  RC is the return code passed
  101.    to the parent process.  If SHOW is non-zero, show the number of
  102.    warnings and errors even if both numbers are zero. */
  103.  
  104. void quit (int rc, int show)
  105. {
  106.   if (save_file != NULL)
  107.     {
  108.       fclose (save_file);
  109.       save_file = NULL;
  110.       remove (save_fname);
  111.     }
  112.   if (warning_count[0] != 0 || warning_count[1] != 0 || show)
  113.     fprintf (stdout, "Total warnings: %d, total errors: %d\n",
  114.              warning_count[0], warning_count[1]);
  115.   if (rc == 0 && warning_count[1] != 0)
  116.     rc = 1;
  117.   exit (rc);
  118. }
  119.  
  120.  
  121. /* Treat `#%lu' in FMT as format specifiers for sector numbers.  We
  122.    cannot introduce our own format specifier (such as `%N') because
  123.    that would cause loads of GCC warnings or we would loose checking
  124.    of format strings. */
  125.  
  126. static void adjust_format_string (char *dst, const char *src)
  127. {
  128.   while (*src != 0)
  129.     if (src[0] != '#' || src[1] != '%' || src[2] != 'l' || src[3] != 'u')
  130.       *dst++ = *src++;
  131.     else
  132.       {
  133.         src += 4;
  134.         switch (sector_number_format)
  135.           {
  136.           case 'x':
  137.             *dst++ = '0'; *dst++ = 'x'; *dst++ = '%';
  138.             *dst++ = '.'; *dst++ = '8'; *dst++ = 'l'; *dst++ = 'x';
  139.             break;
  140.           default:
  141.             *dst++ = '%'; *dst++ = 'l'; *dst++ = 'u';
  142.             break;
  143.           }
  144.       }
  145.   *dst = 0;
  146. }
  147.  
  148.  
  149. /* Like vfprintf(), but treat #%lu specially (sector number).  Return
  150.    the number of characters printed. */
  151.  
  152. int my_vfprintf (FILE *f, const char *fmt, va_list arg_ptr)
  153. {
  154.   char new_fmt[512];
  155.  
  156.   adjust_format_string (new_fmt, fmt);
  157.   return vfprintf (f, new_fmt, arg_ptr);
  158. }
  159.  
  160.  
  161. /* Like fprintf(), but treat #%lu specially (sector number).  Return
  162.    the number of characters printed. */
  163.  
  164. int my_fprintf (FILE *f, const char *fmt, ...)
  165. {
  166.   va_list arg_ptr;
  167.   char new_fmt[512];
  168.   int r;
  169.  
  170.   adjust_format_string (new_fmt, fmt);
  171.   va_start (arg_ptr, fmt);
  172.   r = my_vfprintf (f, new_fmt, arg_ptr);
  173.   va_end (arg_ptr);
  174.   return r;
  175. }
  176.  
  177.  
  178. /* Like vsprintf(), but treat #%lu specially (sector number).  Return
  179.    the number of characters printed. */
  180.  
  181. int my_vsprintf (char *buf, const char *fmt, va_list arg_ptr)
  182. {
  183.   char new_fmt[512];
  184.  
  185.   adjust_format_string (new_fmt, fmt);
  186.   return vsprintf (buf, new_fmt, arg_ptr);
  187. }
  188.  
  189.  
  190. /* Like sprintf(), but treat #%lu specially (sector number).  Return
  191.    the number of characters printed. */
  192.  
  193. int my_sprintf (char *buf, const char *fmt, ...)
  194. {
  195.   va_list arg_ptr;
  196.   char new_fmt[512];
  197.   int r;
  198.  
  199.   adjust_format_string (new_fmt, fmt);
  200.   va_start (arg_ptr, fmt);
  201.   r = my_vsprintf (buf, new_fmt, arg_ptr);
  202.   va_end (arg_ptr);
  203.   return r;
  204. }
  205.  
  206.  
  207. /* Display a fatal error message and terminate the process. */
  208.  
  209. void error (const char *fmt, ...)
  210. {
  211.   va_list arg_ptr;
  212.  
  213.   list_end ();
  214.   fflush (info_file);
  215.   fprintf (stderr, "ERROR: ");
  216.   va_start (arg_ptr, fmt);
  217.   my_vfprintf (stderr, fmt, arg_ptr);
  218.   va_end (arg_ptr);
  219.   fputc ('\n', stderr);
  220.   warning_count[1] += 1;
  221.   quit (2, TRUE);
  222. }
  223.  
  224.  
  225. /* Common code for all functions which display warnings.  Show the
  226.    severity (LEVEL) of the message and increment the appropriate
  227.    counter. */
  228.  
  229. void warning_prolog (int level)
  230. {
  231.   list_end ();
  232.   fflush (info_file);
  233.   switch (level)
  234.     {
  235.     case 0:
  236.       fprintf (diag_file, "WARNING: ");
  237.       break;
  238.     case 1:
  239.       fprintf (diag_file, "ERROR: ");
  240.       break;
  241.     default:
  242.       abort ();
  243.     }
  244.   warning_count[level] += 1;
  245. }
  246.  
  247.  
  248. /* Common code for all functions which display warnings.  This is
  249.    called after printing a message. */
  250.  
  251. void warning_epilog (void)
  252. {
  253.   fflush (diag_file);
  254. }
  255.  
  256.  
  257. /* Display a warning of severity LEVEL (0=warning, 1=error). */
  258.  
  259. void warning (int level, const char *fmt, ...)
  260. {
  261.   va_list arg_ptr;
  262.  
  263.   warning_prolog (level);
  264.   va_start (arg_ptr, fmt);
  265.   my_vfprintf (diag_file, fmt, arg_ptr);
  266.   va_end (arg_ptr);
  267.   fputc ('\n', diag_file);
  268.   warning_epilog ();
  269. }
  270.  
  271.  
  272. /* Continue a warning. */
  273.  
  274. void warning_cont (const char *fmt, ...)
  275. {
  276.   va_list arg_ptr;
  277.  
  278.   va_start (arg_ptr, fmt);
  279.   fputs ("  ", diag_file);
  280.   my_vfprintf (diag_file, fmt, arg_ptr);
  281.   va_end (arg_ptr);
  282.   fputc ('\n', diag_file);
  283.   warning_epilog ();
  284. }
  285.  
  286.  
  287. /* Display information.  No linefeed is appended!  Return the number
  288.    of characters printed. */
  289.  
  290. int info (const char *fmt, ..